package weixin;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;

import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import models.Weixin;
import net.ufrog.common.utils.Strings;
import play.Logger;
import play.cache.Cache;
import utils.json.Gsons;
import weixin.req.Button;
import weixin.resp.AccessToken;
import weixin.resp.Menus;
import weixin.resp.Resp;
import weixin.resp.UserInfo;
import weixin.resp.UserList;


/**
 * 微信请求工具
 * 
 * @author ultrafrog
 * @version 1.0, 2014-11-07
 * @since 1.0
 */
public abstract class WXRequest {

	private static final String CACHE_TOKEN		= "play_weixin_cache_weixin_token_";
	private static final String CACHE_MENU		= "play_weixin_cache_weixin_menu_";
	private static final String URL 			= "https://api.weixin.qq.com/cgi-bin";
	
	/**
	 * @param weixin
	 * @return
	 */
	public static String getAccessToken(Weixin weixin) {
		String token = Cache.get(CACHE_TOKEN + weixin.originalCode, String.class);
		if (token == null) {
			// 请求数据
			String url = String.format("%s/token?grant_type=client_credential&appid=%s&secret=%s", URL, weixin.appId, weixin.appSecret);
			HttpResponse resp = HttpRequest.get(url).send();
			AccessToken atoken = fromResp(resp, AccessToken.class);
			
			// 缓存数据
			Cache.add(CACHE_TOKEN + weixin.originalCode, atoken.accessToken, atoken.expiresIn + "s");
			Logger.info("cache %s access token: %s", weixin.originalCode, atoken.accessToken);
			token = atoken.accessToken;
		}
		return token;
	}
	
	/**
	 * @param resp
	 * @param type
	 * @return
	 */
	protected static <T extends Serializable> T fromResp(HttpResponse resp, Class<T> type) {
		try {
			String json = new String(resp.bodyBytes(), "utf-8");
			Logger.debug("weixin response json: %s", json);
			return Gsons.fromJson(json, type);
		} catch (UnsupportedEncodingException e) {
			throw new play.mvc.results.Error(e.getMessage());
		}
	}
	
	/**
	 * @author ultrafrog
	 * @version 1.0, 2014-11-11
	 * @since 1.0
	 */
	public static class User {
		
		/**
		 * @param weixin
		 * @param nextOpenId
		 * @return
		 */
		public static UserList get(Weixin weixin, String nextOpenId) {
			String url = String.format("%s/user/get?access_token=%s&next_openid=%s", URL, getAccessToken(weixin), Strings.empty(nextOpenId, ""));
			HttpResponse resp = HttpRequest.get(url).send();
			return fromResp(resp, UserList.class);
		}
		
		/**
		 * @param openId
		 * @return
		 */
		public static UserInfo info(Weixin weixin, String openId) {
			String url = String.format("%s/user/info?access_token=%s&openid=%s&lang=%s", URL, getAccessToken(weixin), openId, "zh_CN");
			HttpResponse resp = HttpRequest.get(url).send();
			return fromResp(resp, UserInfo.class);
		}
	}
	
	/**
	 * @author ultrafrog
	 * @version 1.0, 2014-11-09
	 * @since 1.0
	 */
	public static class Menu {
		
		/**
		 * @param weixin
		 * @return
		 */
		public static Menus get(Weixin weixin) {
			Menus menus = Cache.get(CACHE_MENU + weixin.originalCode, Menus.class);
			if (menus == null) {
				// 请求数据
				String url = String.format("%s/menu/get?access_token=%s", URL, getAccessToken(weixin));
				HttpResponse resp = HttpRequest.get(url).send();
				menus = fromResp(resp, Menus.class);
				
				// 缓存数据
				Cache.add(CACHE_MENU + weixin.originalCode, menus);
				Logger.info("cache %s menu.", weixin.originalCode);
			}
			return menus;
		}
		
		/**
		 * @param weixin
		 * @param menus
		 */
		public static Resp create(Weixin weixin, weixin.req.Menu menu) {
			// 发送请求
			String url = String.format("%s/menu/create?access_token=%s", URL, getAccessToken(weixin));
			HttpResponse resp = HttpRequest.post(url).bodyText(Gsons.toJson(menu)).send();
			
			// 处理响应
			Cache.delete(CACHE_MENU + weixin.originalCode);
			return fromResp(resp, Resp.class);
		}
	}
	
	/**
	 * @author ultrafrog
	 * @version 1.0, 2014-11-21
	 * @since 1.0
	 */
	public static class OAuth {
		
		/**
		 * @param weixin
		 * @param code
		 */
		public static AccessToken accessToken(Weixin weixin, String code) {
			String url = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", weixin.appId, weixin.appSecret, code);
			HttpResponse resp = HttpRequest.post(url).send();
			return fromResp(resp, AccessToken.class);
		}
	}
	
	/**
	 * @param args
	 */
	public static void test(Weixin weixin) {
		Button button = new Button();
		button.name = "测试跳转2";
		button.type = Button.Type.VIEW;
		button.url = String.format("https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=1#wechat_redirect", weixin.appId, "http://weixin.ufrog.net/eqxing/index");
		
		weixin.req.Menu menu = new weixin.req.Menu();
		menu.button.add(button);
		WXRequest.Menu.create(weixin, menu);
	}
}
